module klang.klang.工具.klang工具_;
import 全局;
import std.conv: ·to = to;
import ··Klang节点_ = klang.klang.语法节点.Klang节点_;
import ··类型_ = klang.编译.类型.类型_;
import klang.编译.语法节点.节点_: 节点_, 源文件_, 节点数组_, 查找祖先;
import klang.编译.核心.核心_: 整数_, 查找数组索引, 是换行类的, 查找;
import klang.编译.扫描工具.扫描工具_: 跳过杂项, 获取位置的行和列, 获取行开始组;
import klang.编译.工具.工具_: 创建文件诊断消息, 获取节点的源文件, getLocaleSpecificMessage, formatStringFromArgs;
import klang.编译.类型.类型_: 文本范围_, 符号_, 三元结果_;
import klang.编译.诊断.诊断_: 诊断_, 诊断消息_, 诊断包括位置_, 诊断相关信息_, 诊断消息_链_;
import klang.klang.类型.klang类型_: KSK, 节点标志_, 符号标志_;
import klang.klang.语法节点.Klang节点_: Klang源文件_, Klang节点_, 属性访问表达式_, 元素访问表达式_, 二元表达式_, 前缀一元表达式_, 后缀一元表达式_, 循环属于_, 是klang节点, 标识符_, 限定名_, 版本表达式语句_, 变量声明_, 导入从成员_, 导入成员_, 程序声明_, 对象声明_, 结构声明_, 接口声明_, 别名声明_, 类型声明_, 函数声明_, 方法声明_, 形参声明_, 类型形参_, 属性声明_, 枚举成员_, 枚举声明_, 函数表达式_, 箭头函数_, 简洁属性赋值_, 属性赋值_, 调用表达式_, isBlockScope, 是函数类的, 是字面量种类, 是模板字面量种类, 是逻辑运算符, 是赋值运算符, 若是子句_, 默认子句_, 表达式语句_, 如果语句_, 当循环语句_, 返回语句_, 假如语句_, 抛出语句_, 循环语句_, 类型断言表达式_, 类型转换表达式_, 模板中_, 模板尾_, 表达式包含类型实参_, 删除语句_, 延迟语句_, 数组字面量表达式_, 动态类字面量表达式_, 接口字面量表达式_, 结构字面量表达式_, 文本字面量_ = klang文本字面量_, 语句块_ = 块_, 模板表达式_, 导入从声明_, 导入声明_, 导入成员块_, 导入从成员块_, 测试单元语句_, 类型引用_, 元组类型节点_, 类型列表_, 联合类型_, 函数类型_, 构建声明_, 释放声明_, 运算符签名_, 新建表达式_, 表达式列表表达式_, 变量声明列表_, 继承子句_, 若是块_, 断言语句_, 同步语句_, 部分输出表达式_, 是源文件, 获取源文件, 获取程序声明;
enum 赋值种类_ : long {
    None = 0L,
    /** 明确 */
    Definite = 1L,
    /** 复合 */
    Compound = 2L
}
/* @internal */
enum 赋值声明种类_ : int {
    None = 0,
    /// this.name = expr
    ThisProperty = 1,
    // F.name = expr
    Property = 2
}
enum 访问种类_ : int {
    /** Only reads from 种类 variable. */
    读_ = 1,
    /** Only writes to 种类 variable without using the result. E.g.: `x++;`. */
    写_ = 2,
    /** Writes to 种类 variable and uses the result as an expression. E.g.: `f(x++);`. */
    读写_ = 3
}
void 设置节点标志(节点_ n, 节点标志_ 节点标志) {
    n.标志 |= (cast(整数_)(节点标志));
}
long 获取合并节点标志(节点_ 节点, long delegate(节点_) 获取标志) {
    long flags = 获取标志(节点);
    if (节点.目标种类 == KSK.变量声明) {
        节点 = 节点.父节点;
    }
    if (节点 !is ··null!(节点_)) {
        if (节点.目标种类 == KSK.变量声明列表) {
            flags |= 获取标志(节点);
            节点 = 节点.父节点;
        }
    }
    if (节点 !is ··null!(节点_)) {
        if (节点.目标种类 == KSK.变量语句) {
            flags |= 获取标志(节点);
        }
    }
    return flags;
}
long 获取节点标志(节点_ 节点) {
    return .获取合并节点标志(节点, (节点_ n) { return n.标志; });
}
bool 是局部变量声明(变量声明_ n) {
    if ((.获取节点标志(n) & 节点标志_.全局变量_) != 0) {
        return false;
    }
    return true;
}
bool 是点的名称(节点_ 节点) {
    return 节点.目标种类 == KSK.标识符 || 节点.目标种类 == KSK.本体_ || 节点.目标种类 == KSK.原型_ || 节点.目标种类 == KSK.基类_ || 节点.目标种类 == KSK.属性访问表达式 && .是点的名称((cast(属性访问表达式_)(节点)).左侧);
}
bool isLogicalOperator(KSK token) {
    return token == KSK.或或号 || token == KSK.且且号 || token == KSK.叹号;
}
bool isAssignmentOperator(KSK token) {
    return token == KSK.等号 || token >= KSK.第一个复合赋值 && token <= KSK.最后一个复合赋值;
}
赋值种类_ 获取赋值目标种类(节点_ 节点) {
    节点_ 父节点 = 节点.父节点;
    while(true) {
        switch (父节点.目标种类) {
            case KSK.二元表达式: {
                KSK binaryOperator = (cast(二元表达式_)(父节点)).运算符;
                return .isAssignmentOperator(binaryOperator) && (cast(二元表达式_)(父节点)).左侧 == 节点 ? binaryOperator == KSK.等号 ? 赋值种类_.Definite : 赋值种类_.Compound : 赋值种类_.None;
            }
            case KSK.前缀一元表达式: {
                KSK unaryOperator = (cast(前缀一元表达式_)(父节点)).运算符;
                return unaryOperator == KSK.加加号 || unaryOperator == KSK.减减号 ? 赋值种类_.Compound : 赋值种类_.None;
            }
            case KSK.后缀一元表达式: {
                KSK unaryOperator = (cast(后缀一元表达式_)(父节点)).运算符;
                return unaryOperator == KSK.加加号 || unaryOperator == KSK.减减号 ? 赋值种类_.Compound : 赋值种类_.None;
            }
            case KSK.变量声明列表: {
                if (父节点.父节点.目标种类 == KSK.循环属于) {
                    return (cast(循环属于_)(父节点.父节点)).初始化 == 节点.父节点 ? 赋值种类_.Definite : 赋值种类_.None;
                }
                return 赋值种类_.None;
            }
            case KSK.循环属于: {
                return (cast(循环属于_)(父节点)).初始化 == 节点 ? 赋值种类_.Definite : 赋值种类_.None;
            }
            case KSK.展开表达式:
            case KSK.非空表达式:
            case KSK.符号引用表达式: {
                节点 = 父节点;
                break;
            }
            case KSK.简洁属性赋值: {
                if ((cast(简洁属性赋值_)(父节点)).名称 != 节点) {
                    return 赋值种类_.None;
                }
                节点 = 父节点.父节点;
                break;
            }
            case KSK.属性赋值: {
                if ((cast(属性赋值_)(父节点)).名称 == 节点) {
                    return 赋值种类_.None;
                }
                节点 = 父节点.父节点;
                break;
            }
            default: {
                return 赋值种类_.None;
            }
        }
        父节点 = 节点.父节点;
    }
}
bool 是赋值目标(节点_ 节点) {
    return .获取赋值目标种类(节点) != 赋值种类_.None;
}
void setValueDeclaration(符号_ symbol, 节点_ 节点) {
    节点_ 值声明 = symbol.值声明;
    if ((值声明 is ··null!(节点_)) || !((节点.标志 & 节点标志_.Ambient) != 0 && (值声明.标志 & 节点标志_.Ambient) == 0) && (.isAssignmentDeclaration(值声明) && !.isAssignmentDeclaration(节点)) || (值声明.目标种类 != 节点.目标种类 && .isEffectiveModuleDeclaration(值声明))) {
        // other kinds of value declarations take precedence over modules and assignment declarations
        symbol.值声明 = 节点;
    }
}
bool isAssignmentDeclaration(节点_ 节点) {
    if (是klang节点(节点)) {
        //isBinaryExpression(decl) || isAccessExpression(decl) || isIdentifier(decl) || isCallExpression(decl);
        long 种类 = 节点.目标种类;
        return 种类 == KSK.二元表达式 || 种类 == KSK.属性访问表达式 || 种类 == KSK.元素访问表达式 || 种类 == KSK.标识符 || 种类 == KSK.调用表达式;
    }
    return false;
}
bool isEffectiveModuleDeclaration(节点_ 节点) {
    if (是klang节点(节点)) {
        return 节点.目标种类 == KSK.标识符;
    }
    return false;
}
节点_ getExpandoInitializer(节点_ 初始化) {
    if (初始化.目标种类 == KSK.调用表达式) {
        Klang节点_ e = (cast(调用表达式_)(初始化)).表达式;
        if (e.目标种类 == KSK.函数表达式 || e.目标种类 == KSK.箭头函数) {
            return 初始化;
        }
        return ··null!(节点_);
    }
    if (初始化.目标种类 == KSK.函数表达式 || 初始化.目标种类 == KSK.箭头函数) {
        return 初始化;
    }
    if (初始化.目标种类 == KSK.结构字面量表达式 && ((cast(结构字面量表达式_)(初始化)).属性组.length == 0)) {
        return 初始化;
    }
    return ··null!(节点_);
}
节点_ getAssignedExpandoInitializer(节点_ node = ··null!(节点_)) {
    if ((node !is ··null!(节点_)) && (node.父节点 !is ··null!(节点_)) && node.父节点.目标种类 == KSK.二元表达式 && (cast(二元表达式_)(node.父节点)).运算符 == KSK.等号) {
        return .getExpandoInitializer((cast(二元表达式_)(node.父节点)).右侧);
    }
    return ··null!(节点_);
}
节点_ getNameOfExpando(节点_ 节点) {
    if (节点.父节点.目标种类 == KSK.二元表达式) {
        节点_ parent = ((cast(二元表达式_)(节点.父节点)).运算符 == KSK.或或号 && 节点.父节点.父节点.目标种类 == KSK.二元表达式) ? 节点.父节点.父节点 : 节点.父节点;
        if ((cast(二元表达式_)(parent)).目标种类 == KSK.等号 && (cast(二元表达式_)(parent)).目标种类 == KSK.标识符) {
            return (cast(二元表达式_)(parent)).左侧;
        }
    }
    else if (节点.父节点.目标种类 == KSK.变量声明) {
        return (cast(变量声明_)(节点.父节点)).名称;
    }
    return ··null!(节点_);
}
节点_ getNameOfDeclaration(节点_ declaration) {
    if (declaration is ··null!(节点_)) {
        return ··null!(节点_);
    }
    节点_ n = .getNonAssignedNameOfDeclaration(declaration);
    if (n !is ··null!(节点_)) {
        return n;
    }
    if (declaration.目标种类 == KSK.函数表达式) {
        return .getAssignedName(declaration);
    }
    return ··null!(节点_);
}
节点_ getAssignedName(节点_ 节点) {
    if (节点.父节点 is ··null!(节点_)) {
        return ··null!(节点_);
    }
    else if (节点.父节点.目标种类 == KSK.属性访问表达式) {
        return (cast(属性访问表达式_)(节点.父节点)).名称;
    }
    else if (节点.父节点.目标种类 == KSK.二元表达式 && 节点 == (cast(二元表达式_)(节点.父节点)).右侧) {
        if ((cast(二元表达式_)(节点.父节点)).左侧.目标种类 == KSK.标识符) {
            return (cast(二元表达式_)(节点.父节点)).左侧;
        }
        else if ((cast(属性访问表达式_)(节点.父节点)).左侧.目标种类 == KSK.属性访问表达式) {
            return .getElementOrPropertyAccessArgumentExpressionOrName((cast(属性访问表达式_)(节点.父节点)).左侧);
        }
    }
    else if (节点.父节点.目标种类 == KSK.变量声明 && ((cast(变量声明_)(节点.父节点)).名称 !is ··null!(··Klang节点_.Klang标识符_))) {
        return (cast(变量声明_)(节点.父节点)).名称;
    }
    return ··null!(节点_);
}
节点_ getNonAssignedNameOfDeclaration(节点_ declaration) {
    switch (declaration.目标种类) {
        case KSK.版本表达式语句: {
            return (cast(版本表达式语句_)(declaration)).表达式;
        }
        case KSK.导入从成员: {
            if ((cast(导入从成员_)(declaration)).另命名名称 !is ··null!(··Klang节点_.Klang标识符_)) {
                return (cast(导入从成员_)(declaration)).另命名名称;
            }
            return (cast(导入从成员_)(declaration)).名称;
        }
        case KSK.导入成员: {
            return (cast(导入成员_)(declaration)).另命名名称;
        }
        case KSK.标识符: {
            return declaration;
        }
        case KSK.二元表达式: {
            二元表达式_ expr = (cast(二元表达式_)(declaration));
            switch (.getAssignmentDeclarationKind(expr)) {
                case 赋值声明种类_.ThisProperty:
                case 赋值声明种类_.Property: {
                    return .getElementOrPropertyAccessArgumentExpressionOrName((cast(二元表达式_)(expr)).左侧);
                }
                default: {
                    return ··null!(节点_);
                }
            }
        }
        default: break;
    }
    return .获取节点名称(declaration);
}
节点_ getElementOrPropertyAccessArgumentExpressionOrName(节点_ 节点) {
    if (节点.目标种类 == KSK.属性访问表达式) {
        return (cast(属性访问表达式_)(节点)).名称;
    }
    Klang节点_ arg = (cast(元素访问表达式_)(节点)).参数表达式;
    if (arg.目标种类 == KSK.数字字面量 || arg.目标种类 == KSK.文本字面量) {
        return arg;
    }
    return 节点;
}
赋值声明种类_ getAssignmentDeclarationKind(二元表达式_ expr) {
    赋值声明种类_ special = .getAssignmentDeclarationKindWorker(expr);
    return special == 赋值声明种类_.Property ? special : 赋值声明种类_.None;
}
赋值声明种类_ getAssignmentDeclarationKindWorker(二元表达式_ expr) {
    if (expr.运算符 != KSK.等号 || expr.左侧.目标种类 != KSK.属性访问表达式) {
        return 赋值声明种类_.None;
    }
    return .getAssignmentDeclarationPropertyAccessKind(expr.左侧);
}
赋值声明种类_ getAssignmentDeclarationPropertyAccessKind(节点_ lhs) {
    if ((cast(二元表达式_)(lhs)).左侧.目标种类 == KSK.本体_) {
        return 赋值声明种类_.ThisProperty;
    }
    else if (.isBindableStaticNameExpression((cast(属性访问表达式_)(lhs)).左侧, /*排除本体*/ true)) {
        属性访问表达式_ nextToLast = (cast(属性访问表达式_)(lhs));
        while(nextToLast.左侧.目标种类 != KSK.标识符) {
            nextToLast = (cast(属性访问表达式_)(nextToLast.左侧));
        }
        if (.isBindableStaticNameExpression(lhs, /*排除本体*/ true)) {
            // F.G...x = expr
            return 赋值声明种类_.Property;
        }
    }
    return 赋值声明种类_.None;
}
/** Any series of property and element accesses. */
bool isBindableStaticAccessExpression(节点_ 节点, bool 排除本体 = ··null!(bool)) {
    return 节点.目标种类 == KSK.属性访问表达式 && (!排除本体 && (cast(属性访问表达式_)(节点)).左侧.目标种类 == KSK.本体_ || .isBindableStaticNameExpression((cast(属性访问表达式_)(节点)).左侧, /*排除本体*/ true));
}
bool isBindableStaticNameExpression(节点_ 节点, bool 排除本体 = ··null!(bool)) {
    return .isEntityNameExpression(节点) || .isBindableStaticAccessExpression(节点, 排除本体);
}
bool isEntityNameExpression(节点_ 节点) {
    return 节点.目标种类 == KSK.标识符 || .isPropertyAccessEntityNameExpression(节点);
}
bool isPropertyAccessEntityNameExpression(节点_ 节点) {
    return 节点.目标种类 == KSK.属性访问表达式 && .isEntityNameExpression((cast(属性访问表达式_)(节点)).左侧);
}
bool isEntityName(节点_ node) {
    long kind = node.目标种类;
    return kind == KSK.限定名 || kind == KSK.标识符;
}
··Klang节点_.Klang标识符_ getFirstIdentifier(节点_ node) {
    switch (node.目标种类) {
        case KSK.标识符: {
            return (cast(标识符_)(node));
        }
        case KSK.限定名: {
            while(node.目标种类 != KSK.标识符) { }
            return (cast(标识符_)(node));
        }
        case KSK.属性访问表达式: {
            while(node.目标种类 != KSK.标识符) {
                node = (cast(属性访问表达式_)(node)).左侧;
            }
            return (cast(标识符_)(node));
        }
        default: break;
    }
    return ··null!(··Klang节点_.Klang标识符_);
}
··Klang节点_.Klang标识符_ 获取节点名称(节点_ 节点) {
    if (是klang节点(节点)) {
        节点_ n = (cast(节点_)(节点));
        long ksk = n.目标种类;
        switch (ksk) {
            case KSK.导入从成员: {
                导入从成员_ nn = (cast(导入从成员_)(n));
                if (nn.另命名名称 !is ··null!(··Klang节点_.Klang标识符_)) {
                    return nn.另命名名称;
                }
                return nn.名称;
            }
            case KSK.导入成员: {
                导入成员_ nn = (cast(导入成员_)(n));
                if (nn.另命名名称 !is ··null!(··Klang节点_.Klang标识符_)) {
                    return nn.另命名名称;
                }
                return ··null!(··Klang节点_.Klang标识符_);
            }
            case KSK.变量声明: {
                变量声明_ nn = (cast(变量声明_)(n));
                return nn.名称;
            }
            case KSK.程序声明: {
                程序声明_ nn = (cast(程序声明_)(n));
                return nn.名称;
            }
            case KSK.对象声明: {
                对象声明_ nn = (cast(对象声明_)(n));
                return nn.名称;
            }
            case KSK.结构声明: {
                结构声明_ nn = (cast(结构声明_)(n));
                return nn.名称;
            }
            case KSK.接口声明: {
                接口声明_ nn = (cast(接口声明_)(n));
                return nn.名称;
            }
            case KSK.别名声明: {
                别名声明_ nn = (cast(别名声明_)(n));
                return nn.名称;
            }
            case KSK.类型声明: {
                类型声明_ nn = (cast(类型声明_)(n));
                return nn.名称;
            }
            case KSK.函数声明: {
                函数声明_ nn = (cast(函数声明_)(n));
                return nn.名称;
            }
            case KSK.方法声明: {
                方法声明_ nn = (cast(方法声明_)(n));
                return nn.名称;
            }
            case KSK.形参声明: {
                形参声明_ nn = (cast(形参声明_)(n));
                return nn.名称;
            }
            case KSK.类型形参: {
                类型形参_ nn = (cast(类型形参_)(n));
                return nn.名称;
            }
            case KSK.属性声明: {
                属性声明_ nn = (cast(属性声明_)(n));
                return nn.名称;
            }
            case KSK.属性赋值: {
                属性赋值_ nn = (cast(属性赋值_)(n));
                ··Klang节点_.Klang标识符_ 名称 = nn.名称;
                return nn.名称;
            }
            case KSK.简洁属性赋值: {
                简洁属性赋值_ nn = (cast(简洁属性赋值_)(n));
                ··Klang节点_.Klang标识符_ 名称 = nn.名称;
                return nn.名称;
            }
            case KSK.枚举成员: {
                枚举成员_ nn = (cast(枚举成员_)(n));
                return nn.名称;
            }
            default: break;
        }
    }
    return ··null!(··Klang节点_.Klang标识符_);
}
bool 是立即调用表达式(节点_ node) {
    return .获取立即调用函数表达式(node) !is ··null!(调用表达式_);
}
调用表达式_ 获取立即调用函数表达式(节点_ node) {
    if (!是klang节点(node)) {
        return ··null!(调用表达式_);
    }
    节点_ n = (cast(节点_)(node));
    if (n.目标种类 != KSK.函数表达式 && n.目标种类 != KSK.箭头函数) {
        节点_ pren = n;
        节点_ jpn = n.父节点;
        if (jpn is ··null!(节点_)) {
            return ··null!(调用表达式_);
        }
        节点_ pn = (cast(节点_)(jpn));
        while(pn.目标种类 == KSK.属性访问表达式) {
            pren = pn;
            jpn = pn.父节点;
            pn = (cast(节点_)(jpn));
        }
        if (pn.目标种类 == KSK.调用表达式) {
            调用表达式_ cpn = (cast(调用表达式_)(pn));
            if (cpn.表达式 == pren) {
                return cpn;
            }
        }
    }
    return ··null!(调用表达式_);
}
节点_ getEnclosingBlockScopeContainer(节点_ 节点) {
    return 查找祖先(节点.父节点, (节点_ current) {
        if (isBlockScope(current, current.父节点)) {
            return 三元结果_.真_;
        }
        return 三元结果_.假_;
    });
}
bool isSameScopeDescendentOf(节点_ initial, 节点_ parent, 节点_ stopAt) {
    return (parent !is ··null!(节点_)) && (查找祖先(initial, (节点_ n) {
        if (n == stopAt || 是函数类的((cast(Klang节点_)(n)))) {
            return 三元结果_.初始_;
        }
        if (n == parent) {
            return 三元结果_.真_;
        }
        return 三元结果_.假_;
    }) !is ··null!(节点_));
}
节点_ 获取容器对象(节点_ 节点) {
    return 查找祖先(节点.父节点, (节点_ n) {
        if (n.目标种类 == KSK.对象声明) {
            return 三元结果_.真_;
        }
        return 三元结果_.假_;
    });
}
节点_ 获取容器结构体(节点_ 节点) {
    return 查找祖先(节点.父节点, (节点_ n) {
        if (n.目标种类 == KSK.结构声明) {
            return 三元结果_.真_;
        }
        return 三元结果_.假_;
    });
}
节点_ 获取容器类型声明(节点_ 节点) {
    return 查找祖先(节点.父节点, (节点_ n) {
        if (n.目标种类 == KSK.类型声明) {
            return 三元结果_.真_;
        }
        return 三元结果_.假_;
    });
}
访问种类_ 访问种类(节点_ 节点) {
    访问种类_ delegate() 写或读写;
    节点_ 父节点;
    访问种类_ 写或读写·func() {
        return (父节点.父节点 !is ··null!(节点_)) && 父节点.父节点.目标种类 == KSK.表达式语句 ? 访问种类_.写_ : 访问种类_.读写_;
    }
    写或读写 = &写或读写·func;
    父节点 = (cast(节点_)(节点.父节点));
    if (父节点 is ··null!(节点_)) {
        return 访问种类_.读_;
    }
    switch (父节点.目标种类) {
        case KSK.调用表达式: {
            调用表达式_ 调用表达式 = (cast(调用表达式_)(父节点));
            节点数组_!(Klang节点_) 实参组 = 调用表达式.实参组;
            if ((实参组 !is null) && (实参组.原型 !is ··null!(Klang节点_[])) && 实参组.length > 0) {
                long i = 查找数组索引!(Klang节点_)(实参组, (Klang节点_ n) { return n == 节点; });
                if (i != -1) {
                    return 写或读写();
                }
            }
            return 访问种类_.读_;
        }
        case KSK.新建表达式: {
            新建表达式_ 调用表达式 = (cast(新建表达式_)(父节点));
            节点数组_!(Klang节点_) 实参组 = 调用表达式.实参组;
            if ((实参组 !is null) && (实参组.原型 !is ··null!(Klang节点_[])) && 实参组.length > 0) {
                long i = 查找数组索引!(Klang节点_)(实参组, (Klang节点_ n) { return n == 节点; });
                if (i != -1) {
                    return 写或读写();
                }
            }
            return 访问种类_.读_;
        }
        case KSK.前缀一元表达式: {
            KSK 运算符 = (cast(前缀一元表达式_)(父节点)).运算符;
            return 运算符 == KSK.加加号 || 运算符 == KSK.减减号 ? 写或读写() : 访问种类_.读_;
        }
        case KSK.后缀一元表达式: {
            KSK 运算符 = (cast(后缀一元表达式_)(父节点)).运算符;
            return 运算符 == KSK.加加号 || 运算符 == KSK.减减号 ? 写或读写() : 访问种类_.读_;
        }
        case KSK.二元表达式: {
            Klang节点_ 左侧 = (cast(二元表达式_)(父节点)).左侧;
            KSK 运算符 = (cast(二元表达式_)(父节点)).运算符;
            return 左侧 == 节点 && 是赋值运算符(运算符) ? 运算符 == KSK.等号 ? 访问种类_.写_ : 写或读写() : 访问种类_.读_;
        }
        case KSK.属性访问表达式: {
            return (cast(属性访问表达式_)(父节点)).名称 != 节点 ? 访问种类_.读_ : .访问种类(父节点);
        }
        case KSK.属性赋值: {
            访问种类_ 属性访问 = .访问种类(父节点.父节点);
            return 节点 == (cast(属性赋值_)(父节点)).名称 ? .翻转读写种类(属性访问) : 属性访问;
        }
        case KSK.简洁属性赋值: {
            return .访问种类(父节点.父节点);
        }
        case KSK.表达式列表表达式:
        case KSK.动态类字面量表达式:
        case KSK.数组字面量表达式:
        case KSK.词典键值表达式: {
            return .访问种类(父节点);
        }
        default: {
            return 访问种类_.读_;
        }
    }
}
访问种类_ 翻转读写种类(访问种类_ 种类) {
    switch (种类) {
        case 访问种类_.读_: {
            return 访问种类_.写_;
        }
        case 访问种类_.写_: {
            return 访问种类_.读_;
        }
        case 访问种类_.读写_: {
            return 访问种类_.读写_;
        }
        default: {
            return 访问种类_.读写_;
        }
    }
}
诊断包括位置_ createDiagnosticForNodeArray(源文件_ sourceFile, 节点数组_!(节点_) nodes, 诊断消息_ message, dstring arg0 = ··null!(dstring), dstring arg1 = ··null!(dstring), dstring arg2 = ··null!(dstring), dstring arg3 = ··null!(dstring)) {
    long start = 跳过杂项(sourceFile.内容, nodes.开始);
    return 创建文件诊断消息(sourceFile, start, nodes.结束 - start, message, [arg0, arg1, arg2, arg3]);
}
诊断包括位置_ createDiagnosticForNodeInSourceFile(源文件_ sourceFile, 节点_ node, 诊断消息_ message, dstring arg0 = ··null!(dstring), dstring arg1 = ··null!(dstring), dstring arg2 = ··null!(dstring), dstring arg3 = ··null!(dstring)) {
    文本范围_ span = .getErrorSpanForNode(sourceFile, node);
    return 创建文件诊断消息(sourceFile, span.开始, span.结束, message, [arg0, arg1, arg2, arg3]);
}
诊断包括位置_ createDiagnosticForNodeFromMessageChain(节点_ node, 诊断消息_链_ messageChain, 诊断相关信息_[] relatedInformation = ··null!(诊断相关信息_[])) {
    源文件_ sourceFile = 获取节点的源文件(node);
    文本范围_ span = .getErrorSpanForNode(sourceFile, node);
    return .createFileDiagnosticFromMessageChain(sourceFile, span.开始, span.结束, messageChain, relatedInformation);
}
诊断消息_链_ chainDiagnosticMessages(诊断消息_链_[] details, 诊断消息_ message, dstring[] args) {
    args = args.dup;
    dstring text = getLocaleSpecificMessage(message);
    if (args.length > 0 && args[0] != ""d) {
        text = formatStringFromArgs(text, args);
    }
    诊断消息_链_ 诊断链 = new 诊断消息_链_(text);
    诊断链.诊断类别 = message.诊断类别;
    诊断链.代码 = message.代码;
    if (details.length > 0) {
        诊断链.下个 = details;
    }
    return 诊断链;
}
诊断包括位置_ createFileDiagnosticFromMessageChain(源文件_ file, long start, long 长度, 诊断消息_链_ messageChain, 诊断相关信息_[] relatedInformation = ··null!(诊断相关信息_[])) {
    if (messageChain.下个 !is ··null!(诊断消息_链_[])) {
        诊断_ 诊断 = new 诊断_(messageChain.诊断类别, messageChain.代码, messageChain, file.内容, relatedInformation);
        return new 诊断包括位置_(file, start, 长度, 诊断);
    }
    else {
        return new 诊断包括位置_(file, start, 长度, messageChain.诊断类别, messageChain.代码, messageChain.消息文本, file.内容, relatedInformation);
    }
}
文本范围_ getErrorSpanForArrowFunction(源文件_ sourceFile, 箭头函数_ node) {
    long 开始 = 跳过杂项(sourceFile.内容, node.开始);
    if ((node.函数体 !is ··null!(节点_)) && node.函数体.目标种类 == KSK.块) {
        ··类型_.行和列_ 开始行和列 = 获取位置的行和列(sourceFile, node.函数体.开始);
        ··类型_.行和列_ 结束行和列 = 获取位置的行和列(sourceFile, node.函数体.结束);
        long startLine = 开始行和列.行;
        long endLine = 结束行和列.行;
        if (startLine < endLine) {
            // The arrow 函数 spans multiple lines,
            // make the error span be the first line, inclusive.
            return .创建文本范围(开始, .getEndLinePosition(startLine, sourceFile) - 开始 + 1);
        }
    }
    return .创建文本范围(开始, node.结束 - 开始);
}
文本范围_ getErrorSpanForNode(源文件_ sourceFile, 节点_ node) {
    节点_ errorNode = node;
    switch (node.目标种类) {
        case KSK.源文件: {
            long 开始 = 跳过杂项(sourceFile.内容, 0, /*stopAfterLineBreak*/ false);
            if (开始 == sourceFile.内容.length) {
                // file is empty - 返回 span for the beginning of the file
                return .创建文本范围(0, 0);
            }
            return .创建文本范围(开始, 开始 + 1);
        }
        // This list is a work in progress. Add missing node kinds to improve their error
        // spans.
        case KSK.变量声明: {
            errorNode = (cast(变量声明_)(node)).名称;
            break;
        }
        case KSK.对象声明: {
            errorNode = (cast(对象声明_)(node)).名称;
            break;
        }
        case KSK.接口声明: {
            errorNode = (cast(接口声明_)(node)).名称;
            break;
        }
        case KSK.结构声明: {
            errorNode = (cast(结构声明_)(node)).名称;
            break;
        }
        case KSK.枚举声明: {
            errorNode = (cast(枚举声明_)(node)).名称;
            break;
        }
        case KSK.枚举成员: {
            errorNode = (cast(枚举成员_)(node)).名称;
            break;
        }
        case KSK.方法声明: {
            errorNode = (cast(方法声明_)(node)).名称;
            break;
        }
        case KSK.函数声明: {
            errorNode = (cast(函数声明_)(node)).名称;
            break;
        }
        case KSK.函数表达式: {
            errorNode = (cast(函数表达式_)(node)).名称;
            break;
        }
        case KSK.别名声明: {
            errorNode = (cast(别名声明_)(node)).名称;
            break;
        }
        case KSK.类型声明: {
            errorNode = (cast(类型声明_)(node)).名称;
            break;
        }
        case KSK.属性声明: {
            errorNode = (cast(属性声明_)(node)).名称;
            break;
        }
        case KSK.箭头函数: {
            return .getErrorSpanForArrowFunction(sourceFile, (cast(箭头函数_)(node)));
        }
        case KSK.若是子句: {
            long start = 跳过杂项(sourceFile.内容, (cast(若是子句_)(node)).开始);
            long 结束 = (cast(若是子句_)(node)).语句组.length > 0 ? (cast(若是子句_)(node)).语句组[0].开始 : (cast(若是子句_)(node)).结束;
            return .创建文本范围(start, 结束 - start);
        }
        case KSK.默认子句: {
            long start = 跳过杂项(sourceFile.内容, (cast(默认子句_)(node)).开始);
            long 结束 = (cast(默认子句_)(node)).语句组.length > 0 ? (cast(默认子句_)(node)).语句组[0].开始 : (cast(默认子句_)(node)).结束;
            return .创建文本范围(start, 结束 - start);
        }
        default: break;
    }
    if (errorNode is ··null!(节点_)) {
        return .创建文本范围(0, 0);
    }
    bool isMissing = .nodeIsMissing(errorNode);
    long 开始 = isMissing ? errorNode.开始 : 跳过杂项(sourceFile.内容, errorNode.开始);
    if (开始 < 0) {
        开始 = 0;
    }
    return .创建文本范围(开始, errorNode.结束 - 开始);
}
bool nodeIsMissing(节点_ node = ··null!(节点_)) {
    if (node is ··null!(节点_)) {
        return true;
    }
    return node.开始 == node.结束 && node.开始 >= 0 && node.目标种类 != KSK.文件结尾;
}
long getEndLinePosition(long line, 源文件_ sourceFile) {
    long[] lineStarts = 获取行开始组(sourceFile);
    long lineIndex = line;
    dstring sourceText = sourceFile.内容;
    if (lineIndex + 1 == lineStarts.length) {
        // last line - 返回 EOF
        return sourceText.length - 1;
    }
    else {
        // current line start
        long start = lineStarts[lineIndex];
        long pos = lineStarts[lineIndex + 1] - 1;
        while(start <= pos && 是换行类的(sourceText[pos])) {
            --pos;
        }
        return pos;
    }
}
文本范围_ 创建文本范围(long 开始, long 结束) {
    文本范围_ 范围 = new 文本范围_();
    范围.开始 = 开始;
    范围.结束 = 结束;
    return 范围;
}
bool isAccessExpression(节点_ node) {
    return node.目标种类 == KSK.属性访问表达式 || node.目标种类 == KSK.元素访问表达式;
}
dstring getAccessedPropertyName(节点_ access) {
    if (access.目标种类 == KSK.属性访问表达式) {
        return (cast(属性访问表达式_)(access)).名称.标识符.内容;
    }
    else if (access.目标种类 == KSK.元素访问表达式 && (cast(元素访问表达式_)(access)).参数表达式.目标种类 == KSK.文本字面量) {
        return (cast(文本字面量_)((cast(元素访问表达式_)(access)).参数表达式)).内容;
    }
    return ""d;
}
bool 是赋值表达式(节点_ node) {
    return node.目标种类 == KSK.二元表达式 && .isAssignmentOperator((cast(二元表达式_)(node)).运算符);
}
bool isRightSideOfQualifiedNameOrPropertyAccess(节点_ node) {
    return (node.父节点.目标种类 == KSK.限定名 && (cast(限定名_)(node.父节点)).右侧 == node) || (node.父节点.目标种类 == KSK.属性访问表达式 && (cast(属性访问表达式_)(node.父节点)).名称 == node);
}
bool isExpressionNode(节点_ 节点) {
    switch (节点.目标种类) {
        case KSK.本体_:
        case KSK.基类_:
        case KSK.空值_:
        case KSK.空址_:
        case KSK.真_:
        case KSK.假_:
        case KSK.正则表达式字面量:
        case KSK.属性访问表达式:
        case KSK.元素访问表达式:
        case KSK.调用表达式:
        case KSK.新建表达式:
        case KSK.类型断言表达式:
        case KSK.类型转换表达式:
        case KSK.非空表达式:
        case KSK.函数表达式:
        case KSK.箭头函数:
        case KSK.前缀一元表达式:
        case KSK.后缀一元表达式:
        case KSK.二元表达式:
        case KSK.条件表达式:
        case KSK.展开表达式:
        case KSK.模板表达式:
        case KSK.截取表达式:
        case KSK.表达式列表表达式:
        case KSK.词典键值表达式:
        case KSK.符号引用表达式:
        case KSK.结构字面量表达式:
        case KSK.数组字面量表达式:
        case KSK.动态类字面量表达式:
        case KSK.接口字面量表达式:
        case KSK.省略表达式: {
            return true;
        }
        case KSK.标识符:
        case KSK.数字字面量:
        case KSK.文本字面量:
        case KSK.字符字面量:
        case KSK.小数字面量:
        case KSK.无替换模板字面量: {
            return .isInExpressionContext(节点);
        }
        default: {
            return false;
        }
    }
}
bool isInExpressionContext(节点_ node) {
    节点_ 父节点 = node.父节点;
    switch (父节点.目标种类) {
        case KSK.变量声明: {
            return (cast(变量声明_)(父节点)).初始化 == node;
        }
        case KSK.形参声明: {
            return (cast(形参声明_)(父节点)).初始化 == node;
        }
        case KSK.属性声明: {
            return (cast(属性声明_)(父节点)).初始化 == node;
        }
        case KSK.枚举成员: {
            return (cast(属性赋值_)(父节点)).初始化 == node;
        }
        case KSK.属性赋值: {
            return (cast(属性赋值_)(父节点)).初始化 == node;
        }
        case KSK.表达式语句: {
            return (cast(表达式语句_)(父节点)).表达式 == node;
        }
        case KSK.如果语句: {
            return (cast(如果语句_)(父节点)).表达式 == node;
        }
        case KSK.当循环语句: {
            return (cast(当循环语句_)(父节点)).表达式 == node;
        }
        case KSK.返回语句: {
            return (cast(返回语句_)(父节点)).表达式 == node;
        }
        case KSK.假如语句: {
            return (cast(假如语句_)(父节点)).表达式 == node;
        }
        case KSK.若是子句: {
            return (cast(若是子句_)(父节点)).表达式 == node;
        }
        case KSK.抛出语句: {
            return (cast(抛出语句_)(父节点)).表达式 == node;
        }
        case KSK.结构字面量表达式: {
            return (cast(结构字面量表达式_)(父节点)).类型注释节点 != node;
        }
        case KSK.接口字面量表达式: {
            return (cast(接口字面量表达式_)(父节点)).类型 != node;
        }
        case KSK.删除语句: {
            return (cast(删除语句_)(父节点)).表达式 == node;
        }
        case KSK.延迟语句: {
            return (cast(延迟语句_)(父节点)).语句 == node;
        }
        case KSK.循环语句: {
            循环语句_ 循环语句 = (cast(循环语句_)(父节点));
            return (循环语句.初始化 == node && 循环语句.初始化.目标种类 != KSK.变量声明列表) || 循环语句.条件 == node || 循环语句.自增 == node;
        }
        case KSK.循环属于: {
            循环属于_ 循环属于 = (cast(循环属于_)(父节点));
            return (循环属于.初始化 == node && 循环属于.初始化.目标种类 != KSK.变量声明列表) || 循环属于.表达式 == node;
        }
        case KSK.类型转换表达式: {
            return node == (cast(类型转换表达式_)(父节点)).表达式;
        }
        case KSK.类型断言表达式: {
            return node == (cast(类型断言表达式_)(父节点)).表达式;
        }
        case KSK.模板中: {
            return node == (cast(模板中_)(父节点)).表达式;
        }
        case KSK.模板尾: {
            return node == (cast(模板尾_)(父节点)).表达式;
        }
        case KSK.表达式包含类型实参: {
            return (cast(表达式包含类型实参_)(父节点)).表达式 == node && .表达式包含类型实参是表达式(父节点);
        }
        case KSK.简洁属性赋值: {
            return (cast(简洁属性赋值_)(父节点)).初始化 == node;
        }
        default: {
            return .isExpressionNode(父节点);
        }
    }
}
bool 表达式包含类型实参是表达式(节点_ 节点) {
    return 节点.父节点.目标种类 == KSK.新建表达式 || 节点.父节点.目标种类 == KSK.继承子句 && (节点.父节点.父节点.目标种类 == KSK.对象声明 || 节点.父节点.父节点.目标种类 == KSK.结构声明 || 节点.父节点.父节点.目标种类 == KSK.接口声明);
}
bool hasOnlyExpressionInitializer(节点_ node) {
    switch (node.目标种类) {
        case KSK.变量声明:
        case KSK.形参声明:
        case KSK.属性声明:
        case KSK.属性赋值:
        case KSK.枚举成员: {
            return true;
        }
        default: {
            return false;
        }
    }
}
bool isCatchClauseVariableDeclarationOrBindingElement(节点_ node) {
    return node.目标种类 == KSK.变量声明 && node.父节点.目标种类 == KSK.捕获子句;
}
节点数组_!(节点_) getContainingNodeArray(节点_ node) {
    if (node.父节点 is ··null!(节点_)) {
        return ··null!(节点数组_!(节点_));
    }
    long nk = node.目标种类;
    节点_ 父节点 = node.父节点;
    switch (父节点.目标种类) {
        case KSK.导入从声明: {
            return ·to!(节点数组_!(节点_))((cast(导入从声明_)(父节点)).导入组);
        }
        case KSK.导入声明: {
            return ·to!(节点数组_!(节点_))((cast(导入声明_)(父节点)).导入组);
        }
        case KSK.导入成员块: {
            return ·to!(节点数组_!(节点_))((cast(导入成员块_)(父节点)).语句组);
        }
        case KSK.导入从成员块: {
            return ·to!(节点数组_!(节点_))((cast(导入从成员块_)(父节点)).语句组);
        }
        case KSK.测试单元语句: {
            return ·to!(节点数组_!(节点_))((cast(测试单元语句_)(父节点)).语句组);
        }
        case KSK.块: {
            return ·to!(节点数组_!(节点_))((cast(语句块_)(父节点)).语句组);
        }
        case KSK.程序声明: {
            return ·to!(节点数组_!(节点_))((cast(程序声明_)(父节点)).语句组);
        }
        case KSK.模板表达式: {
            return ·to!(节点数组_!(节点_))((cast(模板表达式_)(父节点)).模板跨度);
        }
        case KSK.类型引用: {
            return ·to!(节点数组_!(节点_))((cast(类型引用_)(父节点)).类型实参组);
        }
        case KSK.元组类型节点: {
            return ·to!(节点数组_!(节点_))((cast(元组类型节点_)(父节点)).类型组);
        }
        case KSK.类型列表: {
            return ·to!(节点数组_!(节点_))((cast(类型列表_)(父节点)).类型组);
        }
        case KSK.联合类型: {
            return ·to!(节点数组_!(节点_))((cast(联合类型_)(父节点)).类型组);
        }
        case KSK.函数类型: {
            return new 节点数组_!(节点_)(nk == KSK.类型形参 ? ·to!(节点数组_!(节点_))((cast(函数类型_)(父节点)).类型形参) : ·to!(节点数组_!(节点_))((cast(函数类型_)(父节点)).形参组));
        }
        case KSK.箭头函数: {
            return new 节点数组_!(节点_)(nk == KSK.类型形参 ? ·to!(节点数组_!(节点_))((cast(箭头函数_)(父节点)).类型形参) : ·to!(节点数组_!(节点_))((cast(箭头函数_)(父节点)).形参组));
        }
        case KSK.函数表达式: {
            return new 节点数组_!(节点_)(nk == KSK.类型形参 ? ·to!(节点数组_!(节点_))((cast(函数表达式_)(父节点)).类型形参) : ·to!(节点数组_!(节点_))((cast(函数表达式_)(父节点)).形参组));
        }
        case KSK.函数声明: {
            return new 节点数组_!(节点_)(nk == KSK.类型形参 ? ·to!(节点数组_!(节点_))((cast(函数声明_)(父节点)).类型形参) : ·to!(节点数组_!(节点_))((cast(函数声明_)(父节点)).形参组));
        }
        case KSK.构建声明: {
            return new 节点数组_!(节点_)(nk == KSK.类型形参 ? ·to!(节点数组_!(节点_))((cast(构建声明_)(父节点)).类型形参) : ·to!(节点数组_!(节点_))((cast(构建声明_)(父节点)).形参组));
        }
        case KSK.释放声明: {
            return new 节点数组_!(节点_)(nk == KSK.类型形参 ? ·to!(节点数组_!(节点_))((cast(释放声明_)(父节点)).类型形参) : ·to!(节点数组_!(节点_))((cast(释放声明_)(父节点)).形参组));
        }
        case KSK.方法声明: {
            return new 节点数组_!(节点_)(nk == KSK.类型形参 ? ·to!(节点数组_!(节点_))((cast(方法声明_)(父节点)).类型形参) : ·to!(节点数组_!(节点_))((cast(方法声明_)(父节点)).形参组));
        }
        case KSK.接口声明: {
            return ·to!(节点数组_!(节点_))(nk == KSK.类型形参 ? ·to!(节点数组_!(节点_))((cast(接口声明_)(父节点)).类型形参) : ·to!(节点数组_!(节点_))(nk == KSK.继承子句 ? ·to!(节点数组_!(节点_))((cast(接口声明_)(父节点)).继承子句) : ·to!(节点数组_!(节点_))((cast(接口声明_)(父节点)).成员组)));
        }
        case KSK.枚举声明: {
            return ·to!(节点数组_!(节点_))((cast(枚举声明_)(父节点)).成员组);
        }
        case KSK.对象声明: {
            return ·to!(节点数组_!(节点_))(nk == KSK.类型形参 ? ·to!(节点数组_!(节点_))((cast(对象声明_)(父节点)).类型形参) : ·to!(节点数组_!(节点_))(nk == KSK.继承子句 ? ·to!(节点数组_!(节点_))((cast(对象声明_)(父节点)).继承子句) : ·to!(节点数组_!(节点_))((cast(对象声明_)(父节点)).成员组)));
        }
        case KSK.结构声明: {
            return ·to!(节点数组_!(节点_))(nk == KSK.类型形参 ? ·to!(节点数组_!(节点_))((cast(结构声明_)(父节点)).类型形参) : ·to!(节点数组_!(节点_))(nk == KSK.继承子句 ? ·to!(节点数组_!(节点_))((cast(结构声明_)(父节点)).继承子句) : ·to!(节点数组_!(节点_))((cast(结构声明_)(父节点)).成员组)));
        }
        case KSK.类型声明: {
            return ·to!(节点数组_!(节点_))(nk == KSK.类型形参 ? ·to!(节点数组_!(节点_))((cast(类型声明_)(父节点)).类型形参) : ·to!(节点数组_!(节点_))((cast(类型声明_)(父节点)).成员组));
        }
        case KSK.运算符签名: {
            return ·to!(节点数组_!(节点_))((cast(运算符签名_)(父节点)).运算符组);
        }
        case KSK.数组字面量表达式: {
            return ·to!(节点数组_!(节点_))((cast(数组字面量表达式_)(父节点)).元素组);
        }
        case KSK.接口字面量表达式: {
            return ·to!(节点数组_!(节点_))((cast(接口字面量表达式_)(父节点)).属性组);
        }
        case KSK.结构字面量表达式: {
            return ·to!(节点数组_!(节点_))((cast(结构字面量表达式_)(父节点)).属性组);
        }
        case KSK.新建表达式: {
            return ·to!(节点数组_!(节点_))((cast(新建表达式_)(父节点)).实参组);
        }
        case KSK.调用表达式: {
            if (((cast(调用表达式_)(父节点)).类型实参组 !is null) && ((cast(调用表达式_)(父节点)).类型实参组.原型 !is ··null!(Klang节点_[]))) {
                long i = 查找数组索引!(Klang节点_)((cast(调用表达式_)(父节点)).类型实参组, (Klang节点_ n) { return n == node; });
                return ·to!(节点数组_!(节点_))(i != -1 ? ·to!(节点数组_!(节点_))((cast(调用表达式_)(父节点)).类型实参组) : ·to!(节点数组_!(节点_))((cast(调用表达式_)(父节点)).实参组));
            }
            else {
                return ·to!(节点数组_!(节点_))((cast(调用表达式_)(父节点)).实参组);
            }
        }
        case KSK.表达式包含类型实参: {
            return ·to!(节点数组_!(节点_))((cast(表达式包含类型实参_)(父节点)).类型实参组);
        }
        case KSK.表达式列表表达式: {
            return ·to!(节点数组_!(节点_))((cast(表达式列表表达式_)(父节点)).元素组);
        }
        case KSK.变量声明列表: {
            return ·to!(节点数组_!(节点_))((cast(变量声明列表_)(父节点)).声明组);
        }
        case KSK.继承子句: {
            return ·to!(节点数组_!(节点_))((cast(继承子句_)(父节点)).类型组);
        }
        case KSK.若是子句: {
            return ·to!(节点数组_!(节点_))((cast(若是子句_)(父节点)).语句组);
        }
        case KSK.默认子句: {
            return ·to!(节点数组_!(节点_))((cast(默认子句_)(父节点)).语句组);
        }
        case KSK.若是块: {
            return ·to!(节点数组_!(节点_))((cast(若是块_)(父节点)).子句组);
        }
        case KSK.断言语句: {
            return ·to!(节点数组_!(节点_))((cast(断言语句_)(父节点)).实参组);
        }
        case KSK.同步语句: {
            if (((cast(同步语句_)(父节点)).实参组 !is null) && ((cast(同步语句_)(父节点)).实参组.原型 !is ··null!(Klang节点_[]))) {
                long i = 查找数组索引!(Klang节点_)((cast(同步语句_)(父节点)).实参组, (Klang节点_ n) { return n == node; });
                return ·to!(节点数组_!(节点_))(i != -1 ? ·to!(节点数组_!(节点_))((cast(同步语句_)(父节点)).实参组) : ·to!(节点数组_!(节点_))((cast(同步语句_)(父节点)).语句组));
            }
            else {
                return ·to!(节点数组_!(节点_))((cast(同步语句_)(父节点)).语句组);
            }
        }
        case KSK.源文件: {
            return (cast(源文件_)(父节点)).语句组;
        }
        default: break;
    }
    return ··null!(节点数组_!(节点_));
}
节点_ getContainingClass(节点_ node) {
    return 查找祖先(node.父节点, (节点_ n) {
        if (n.目标种类 == KSK.对象声明 || n.目标种类 == KSK.结构声明) {
            return 三元结果_.真_;
        }
        if (n.目标种类 == KSK.程序声明) {
            return 三元结果_.初始_;
        }
        return 三元结果_.假_;
    });
}
程序声明_ 获取源文件的程序集(Klang源文件_ n) {
    节点_ 程序声明 = 查找!(节点_)(n.语句组, (节点_ n) { return n.目标种类 == KSK.程序声明; });
    return 获取程序声明(程序声明);
}
程序声明_ 获取节点的程序集(节点_ node) {
    if (是源文件(node)) {
        return .获取源文件的程序集(获取源文件(node));
    }
    节点_ ret = 查找祖先(node, (节点_ n) {
        if (n.目标种类 == KSK.程序声明) {
            return 三元结果_.真_;
        }
        if (n.目标种类 == KSK.源文件) {
            return 三元结果_.初始_;
        }
        return 三元结果_.假_;
    });
    return (cast(程序声明_)(ret));
}
bool isExpression(节点_ n) {
    while(n.目标种类 == KSK.部分输出表达式) {
        n = (cast(部分输出表达式_)(n)).表达式;
    }
    long 种类 = n.目标种类;
    switch (种类) {
        case KSK.本体_:
        case KSK.基类_:
        case KSK.空值_:
        case KSK.空址_:
        case KSK.真_:
        case KSK.假_:
        case KSK.正则表达式字面量:
        case KSK.属性访问表达式:
        case KSK.元素访问表达式:
        case KSK.调用表达式:
        case KSK.新建表达式:
        case KSK.类型断言表达式:
        case KSK.类型转换表达式:
        case KSK.非空表达式:
        case KSK.函数表达式:
        case KSK.箭头函数:
        case KSK.前缀一元表达式:
        case KSK.后缀一元表达式:
        case KSK.二元表达式:
        case KSK.条件表达式:
        case KSK.展开表达式:
        case KSK.模板表达式:
        case KSK.截取表达式:
        case KSK.表达式列表表达式:
        case KSK.词典键值表达式:
        case KSK.符号引用表达式:
        case KSK.标识符:
        case KSK.数字字面量:
        case KSK.文本字面量:
        case KSK.字符字面量:
        case KSK.小数字面量:
        case KSK.无替换模板字面量:
        case KSK.结构字面量表达式:
        case KSK.数组字面量表达式:
        case KSK.动态类字面量表达式:
        case KSK.接口字面量表达式:
        case KSK.省略表达式: {
            return true;
        }
        default: break;
    }
    return false;
}
符号标志_ 获取扩展符号标志(long ksk) {
    switch (ksk) {
        case KSK.纯净_: {
            return 符号标志_.纯净_;
        }
        case KSK.安全_: {
            return 符号标志_.安全_;
        }
        case KSK.信任_: {
            return 符号标志_.信任_;
        }
        case KSK.系统_: {
            return 符号标志_.系统_;
        }
        case KSK.无回收_: {
            return 符号标志_.无回收_;
        }
        case KSK.不抛出_: {
            return 符号标志_.不抛出_;
        }
        case KSK.声明_: {
            return 符号标志_.声明_;
        }
        case KSK.私有_: {
            return 符号标志_.私有_;
        }
        case KSK.保护_: {
            return 符号标志_.保护_;
        }
        case KSK.重载_: {
            return 符号标志_.重载_;
        }
        case KSK.只读_: {
            return 符号标志_.只读_;
        }
        case KSK.恒定_: {
            return 符号标志_.恒定_;
        }
        case KSK.共享_: {
            return 符号标志_.共享_;
        }
        case KSK.静态_: {
            return 符号标志_.静态_;
        }
        case KSK.引用_: {
            return 符号标志_.引用_;
        }
        case KSK.局部_: {
            return 符号标志_.局部_;
        }
        case KSK.固定_: {
            return 符号标志_.固定_;
        }
        case KSK.返回_: {
            return 符号标志_.返回_;
        }
        case KSK.导出_: {
            return 符号标志_.导出_;
        }
        case KSK.外部_:
        case KSK.外部修饰符声明: {
            return 符号标志_.外部_;
        }
        case KSK.返回局部引用_: {
            return 符号标志_.返回局部引用_;
        }
        case KSK.返回引用_: {
            return 符号标志_.返回引用_;
        }
        case KSK.局部引用_: {
            return 符号标志_.局部引用_;
        }
        case KSK.返回局部_: {
            return 符号标志_.返回局部_;
        }
        default: break;
    }
    return 符号标志_.无_;
}
